/**
 * Create  2006-8-15
 */
package com.ai.core.util;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;




/**
 *  This static class �ṩ���ַ������� :
 *  <li>
 *  	* �ַ���Ч���ж�
 *      * cache of jndi context,
 *      * lookup EJB,
 *      * home factory,
 * </li>
 * @author xiaoenK
 *
 */

public class ToolBox {

    /**
     *  ���� an empty string
     */
    public final static String EMPTY_STRING = "";

    /**
     *  Defines a quote
     */
    public final static char QUOTE_CHAR = '\'';

    /**
     *  Defines a double quote pattern
     */
    public final static String DOUBLE_QUOTE_STRING = "''";

    /**
     *  Defines ����й���׵�Ĭ��ʱ���ʽ
     */
    private static SimpleDateFormat formater = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" );

    private static SimpleDateFormat formatersss = new SimpleDateFormat("yyyyMMddHHmmssSSS");

    private static SimpleDateFormat formaterNormal = new SimpleDateFormat("yyyyMMddHHmmss");

    /**
     *  ����context,��ΪGetting the Initial context ��һ���ǳ�����Ĳ���
     */
    private static Context _context;

    public static String formaterNormal(Date date) {
		return formaterNormal.format(date);
	}
    public static String formatDateTime(Date date) {
		return formatersss.format(date);
	}
    /**
     *  �Ը��ַ���ж�,�ǿշ�����,��Ȼ��""Ҳ��Ϊ��Ҳ
     */
    public static boolean isCorrect( String p_Parameter ) {
        boolean bTmpCheckResult = false;

        if ( ( p_Parameter != null ) && ( !p_Parameter.equals( EMPTY_STRING ) ) )
            bTmpCheckResult = true;

        return bTmpCheckResult;
    }
    /**
     *  �Ը������ж�,���Ϊ�շ�����
     */
    public static boolean isCorrect( Object p_Parameter ) {
    	if(p_Parameter instanceof String){
    		return isCorrect((String)p_Parameter);
    	}
        if ( p_Parameter != null )
            return true;

        return false;
    }

	public static void notEmpty(Object object, String message) {
		if (!isCorrect(object)) {
			throw new IllegalArgumentException(message);
		}

	}

	public static void notNull(Object object, String message) {
		if(object instanceof String){
			String o = (String) object;
			if(!isCorrect(o)){
				throw new IllegalArgumentException(message);
			}
		}else{
			if (object == null) {
				throw new IllegalArgumentException(message);
			}
		}

	}

	public static void notEmpty(Object[] array, String message) {
		if (isEmpty(array)) {
			throw new IllegalArgumentException(message);
		}
	}

	public static boolean isEmpty(Object[] array) {
		return (array == null || array.length == 0);
	}


	/**
	 * ���ַ�ת��������,���Ƿ��ַ��쳣 add by xiaonek
	 * @param numberSring
	 * @return
	 */
	public static Integer string2Integer(String numberSring) {
		if (isDigit(numberSring)) {
			return Integer.valueOf(numberSring);
		}
		return null;
	}

	/**
	 * ���ַ�ת��������,���Ƿ��ַ��쳣 add by xiaonek
	 * @param numberSring
	 * @return
	 */
	public static Long string2Long(String numberSring){
		if (isDigit(numberSring)){
			return Long.valueOf(numberSring);
		}
		return null;
	}

	public static boolean String2Boolean(String booleanString){
		if(!isCorrect(booleanString))
			return false;
		if(booleanString.equalsIgnoreCase("1"))
			return true;
		if(booleanString.equalsIgnoreCase("true"))
			return true;
		if(booleanString.equalsIgnoreCase("yes") || booleanString.equalsIgnoreCase("y"))
			return true;
		return false;
	}

	public static String boolean2String(boolean b){
		return b?"1":"0";
	}

	public static boolean isDigit(String numberString){
		if (isCorrect(numberString)){
			for (int i = 0; i < numberString.length(); i++) {
				if (!Character.isDigit(numberString.charAt(i))){
					throw new IllegalArgumentException("�ַ�"+numberString+"��������");
				}
			}
			return true;
		}
		return false;
	}



	/**
	 * ����0��ǰ׺��
	 * @param userSeq
	 * @param length
	 * @return
	 */
	public static String fillZero(String userSeq, int length) {
		return fillZero(userSeq,length,true);
	}
	/**
	 *
	 * @param userSeq
	 * @param length ��0����
	 * @param isBefore �Ƿ���ǰ������
	 * @return
	 */
	public static String fillZero(String userSeq, int length,boolean isBefore) {
		StringBuffer sb = new StringBuffer();
		while (length >0) {
			sb.append("0");
			length--;
		}
		if(isBefore){
			return sb.toString()+userSeq;
		}else{
			return userSeq + sb.toString();
		}
	}


    /**
     * ob1,ob2����Ƚ�.
     * If ob1 if null then ob2 must be null.
     * If ob1 if not null ob2 must be equal to ob1.
     */
    public static boolean isEqual( Object ob1, Object ob2 ) {
        boolean result = true;

        if ( ob1 == null ) {
            result = result && ( ob2 == null );
        } else {
            result = result && ( ob1.equals( ob2 ) );
        }

        return result;
    }

    /**
     *  Get a remote reference to the client JTA interface.
     */
//    public static UserTransaction getJTA() throws Exception {
//        UserTransaction jta;
//
//        try {
//            jta = (UserTransaction) getContext().lookup( "javax.transaction.UserTransaction" );
//        } catch( Exception e ) {
//            // Reset the connection to the context.
//            _context = null;
//            jta = (UserTransaction) getContext().lookup( "javax.transaction.UserTransaction" );
//        }
//
//        return jta;
//    }


    public static Context getContext() throws NamingException {

        if ( _context != null ) {
            return _context;
        }
        return ( _context = new InitialContext() );
    }

    public static Object lookUpResource(String jndiName){
    	Object resource = null;
    	try {
    		resource = getContext().lookup(jndiName);
		} catch (NamingException e) {
			e.printStackTrace();
		}
		if(resource == null){
			throw new RuntimeException("������������Դ��" + jndiName);
		}
		return resource;
    }

    /**
     *  Narrow ���϶���,ǰ�����Դ��narrowingClass
     */
    public static Collection narrowCollection( Collection collection, Class narrowingClass ) {

        Collection resultCollection = new ArrayList();
        Iterator iterator = collection.iterator();

        while ( iterator.hasNext() ) {
            resultCollection.add( PortableRemoteObject.narrow( iterator.next(), narrowingClass ) );
        }

        return resultCollection;
    }

    /**
     *  Lookup for an ejb home ͨ��JNDI���. Ӧ�� narrowing.
     *  ��Ȼͨ��˷���,�����Ի��EJBLocalHome
     */
    public static Object lookUpEJB( String p_sEJBName, Class p_cEJBClass ) throws NamingException {
        Object objref;

        try {
            objref = getContext().lookup( p_sEJBName );
        } catch( NamingException e ) {
            // Try to rebind the context
            _context = null;
            objref = getContext().lookup( p_sEJBName );
        }

        return PortableRemoteObject.narrow( objref, p_cEJBClass );
    }


    public static String notEmpty( String p_string ) {
        if ( "".equals( p_string ) ) {
            return null;
        } else {
            return p_string;
        }
    }

    public static String getCommaSeparated( Collection p_collection ) {
        StringBuffer sb = new StringBuffer();
        Iterator iter = p_collection.iterator();

        if ( iter.hasNext() ) {
            sb.append( iter.next().toString() );

            while ( iter.hasNext() ) {
                sb.append( ", " );
                sb.append( iter.next().toString() );
            }
        }
        return sb.toString();
    }

    
    /**
     *  ��� a new OID for the given sequence
     */
    public static Date getSysdateFromDatabase( Connection p_connection ) throws SQLException {

    	Date sysdate = null;
        Statement statement = null;
        ResultSet resultSet = null;

        //���sql���
        String sbQuery = new String( "SELECT sysdate FROM dual " );


        try {
            statement = p_connection.createStatement();
            resultSet = statement.executeQuery(sbQuery);
            resultSet.next();
            sysdate = resultSet.getDate(1) ;
        } finally {
            // close connecion
            if ( resultSet != null ) {
                resultSet.close();
            }
            if ( statement != null ) {
                statement.close();
            }
        }
        //finally
        return sysdate;
    }
    
    /**
     *  ��� a new OID for the given sequence
     */
    public static Long getNewOID( String p_sequence, Connection p_connection ) throws SQLException {

        Long lOID = null;
        Statement statement = null;
        ResultSet resultSet = null;

        //���sql���
        StringBuffer sbQuery = new StringBuffer( "SELECT " );
        sbQuery.append( p_sequence );
        sbQuery.append( ".NEXTVAL FROM DUAL" );

        try {
            statement = p_connection.createStatement();
            resultSet = statement.executeQuery( sbQuery.toString() );
            resultSet.next();
            lOID = new Long( resultSet.getLong( 1 ) );
        } finally {
            // close connecion
            if ( resultSet != null ) {
                resultSet.close();
            }
            if ( statement != null ) {
                statement.close();
            }
        }
        //finally
        return lOID;
    }
    /**
     * ��һ��String��,��p_newText �滻 p_oldText
     */
    public static String replacePattern( String p_stringToParse, String p_oldText, String p_newText ) {
        int index;
        int lenght = p_oldText.length();

        while ( ( index = p_stringToParse.lastIndexOf( p_oldText ) ) != -1 ) {
            p_stringToParse = p_stringToParse.substring( 0, index ) + p_newText + p_stringToParse.substring( index + lenght );
        }

        return p_stringToParse;
    }

    private static final ThreadLocal resources = new ThreadLocal();
	private static final Log logger = LogFactory.getLog(ToolBox.class);


    /**
	 * Check if there is a resource for the given key bound to the current
	 * thread.
	 *
	 * @param key
	 *            the key to check (usually the resource factory)
	 * @return if there is a value bound to the current thread
	 * @see ResourceTransactionManager#getResourceFactory()
	 */
	public static boolean hasResource(Object key) {
		ToolBox.notNull(key, "Key must not be null");
		Map map = (Map) resources.get();
		return (map != null && map.containsKey(key));
	}

	/**
	 * Retrieve a resource for the given key that is bound to the current
	 * thread.
	 *
	 * @param key
	 *            the key to check (usually the resource factory)
	 * @return a value bound to the current thread (usually the active resource
	 *         object), or <code>null</code> if none
	 * @see ResourceTransactionManager#getResourceFactory()
	 */
	public static Object getResource(Object key) {
		ToolBox.notNull(key, "Key must not be null");
		Map map = (Map) resources.get();
		if (map == null) {
			return null;
		}
		Object value = map.get(key);
		if (value != null && logger.isDebugEnabled()) {
			logger
					.debug("Retrieved value [" + value + "] for key [" + key + "] bound to thread [" + Thread.currentThread().getName()
							+ "]");
		}
		return value;
	}

	/**
	 * Bind the given resource for the given key to the current thread.
	 *
	 * @param key
	 *            the key to bind the value to (usually the resource factory)
	 * @param value
	 *            the value to bind (usually the active resource object)
	 * @throws IllegalStateException
	 *             if there is already a value bound to the thread
	 * @see ResourceTransactionManager#getResourceFactory()
	 */
	public static void bindResource(Object key, Object value) throws IllegalStateException {
		ToolBox.notNull(key, "Key must not be null");
		ToolBox.notNull(value, "Value must not be null");
		Map map = (Map) resources.get();
		// set ThreadLocal Map if none found
		if (map == null) {
			map = new HashMap();
			resources.set(map);
		}
		if (map.containsKey(key)) {
			logger.warn("Already value [" + map.get(key) + "] for key [" + key + "] bound to thread ["
					+ Thread.currentThread().getName() + "]");
//			throw new IllegalStateException("Already value [" + map.get(key) + "] for key [" + key + "] bound to thread ["
//					+ Thread.currentThread().getName() + "]");
		}
		map.put(key, value);
		if (logger.isDebugEnabled()) {
			logger.debug("Bound value [" + value + "] for key [" + key + "] to thread [" + Thread.currentThread().getName() + "]");
		}
	}

	/**
	 * Unbind a resource for the given key from the current thread.
	 *
	 * @param key
	 *            the key to unbind (usually the resource factory)
	 * @return the previously bound value (usually the active resource object)
	 * @throws IllegalStateException
	 *             if there is no value bound to the thread
	 * @see ResourceTransactionManager#getResourceFactory()
	 */
	public static Object unbindResource(Object key) throws IllegalStateException {
		ToolBox.notNull(key, "Key must not be null");
		Map map = (Map) resources.get();
		if (map == null || !map.containsKey(key)) {
			//ignore
			logger.info("No value for key [" + key + "] bound to thread [" + Thread.currentThread().getName() + "]");
			return null;
		}
		Object value = map.remove(key);
		// remove entire ThreadLocal if empty
		if (map.isEmpty()) {
			resources.set(null);
		}
		if (logger.isDebugEnabled()) {
			logger.debug("Removed value [" + value + "] for key [" + key + "] from thread [" + Thread.currentThread().getName() + "]");
		}
		return value;
	}

	public static String setStringParamValue(String inPackage, String paramKey,String value){
		ToolBox.notNull(value,"�滻��ֵ������Ϊ��!");
		if(ToolBox.isCorrect(inPackage) && ToolBox.isCorrect(paramKey)){
			if(ToolBox.isCorrect(inPackage) && ToolBox.isCorrect(paramKey)){
				if(!paramKey.startsWith("\"")){
					paramKey = "\"" + paramKey;
				}
				if(!paramKey.endsWith("\"")){
					paramKey = paramKey +"\"";
				}
				int paramIndex = inPackage.indexOf(paramKey);
				if(paramIndex != -1){
					paramIndex = paramIndex + paramKey.length() + 1;
					int begin=0,end=0;
					begin = inPackage.indexOf("\"",paramIndex) +1;
					end = inPackage.indexOf("\"",begin);
					StringBuilder sb = new StringBuilder();
					sb.append(inPackage.substring(0,begin));
					sb.append(value);
					sb.append(inPackage.substring(end));
					return sb.toString();
				}
			}
		}
		return inPackage;

	}
	public static String getStringParamValue(String inPackage, String paramKey){
		String value=null;
		if(ToolBox.isCorrect(inPackage) && ToolBox.isCorrect(paramKey)){
			if(!paramKey.startsWith("\"")){
				paramKey = "\"" + paramKey;
			}
			if(!paramKey.endsWith("\"")){
				paramKey = paramKey +"\"";
			}
			int paramIndex = inPackage.indexOf(paramKey);
			if(paramIndex != -1){
				paramIndex = paramIndex + paramKey.length() + 1;
				int begin=0,end=0;
				begin = inPackage.indexOf("\"",paramIndex) +1;
				end = inPackage.indexOf("\"",begin);
				value = inPackage.substring(begin,end);
			}
		}
		return value;
	}

}

